import {Button, Col, Row, Space, Tooltip, Tree, TreeDataNode, TreeProps} from "antd";
import React, {useEffect, useState} from "react";

import styles from '../ColumnsMap/index.less';
import {DoubleLeftOutlined, DoubleRightOutlined, MinusCircleOutlined} from "@ant-design/icons";

export type ColumnGroupProps = {
  id?:string;
  initialValue?: API.ColumnGroupDTO;
  value?: API.CreateColumnGroupDTO;
  onChange?: (value: API.CreateColumnGroupDTO) => void;
};

const lookup = (data: TreeDataNode[], key: React.Key,
                callback: (matchNode: TreeDataNode, matchIndex: number, sourceData: TreeDataNode[]) => void) => {
  for (let i = 0; i < data.length; i++) {
    if (data[i].key === key) {
      return callback(data[i], i, data);
    }
    if (data[i].children) {
      lookup(data[i].children!, key, callback);
    }
  }
};

const onRemove = (node: TreeDataNode,
                  data: TreeDataNode[],
                  updateFunc: (newData: TreeDataNode[], n: TreeDataNode) => void) => {
  const copyData = [...data];
  // find match index
  let matchIndex;
  lookup(copyData, node.key, (_, i) => matchIndex = i);
  copyData.splice(matchIndex!, 1);
  updateFunc(copyData, node);
}

const ColumnGroup: React.FC<ColumnGroupProps> = (props) => {

  const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
  const [checkedData, setCheckedData] = useState<TreeDataNode[]>([]);
  const [treeData, setTreeData] = useState<TreeDataNode[]>([]);
  // 初始化参数

// 源搜索
  const triggerOnChange = () => {
    const columns :string[]  = checkedData.map(i => i.key as string);
    props?.onChange?.({...props?.value,columnPairs:columns})
  }

  // useState非实时更新，使用useEffect监听实现Form的onchange变更
  useEffect(() => {
    triggerOnChange();
  }, [checkedData]);

  useEffect(() => {
    const preColumnPairs = props?.initialValue?.preColumnPairs;
    if (preColumnPairs){
     const  prePairs = preColumnPairs
       .map(p => ({title:(p?.sourceColumn?.name || '') + '-' + ( p?.targetColumn?.name || ''),key:(p?.sourceColumn?.name || '') + ':' + ( p?.targetColumn?.name || '')}));
     setTreeData(prePairs);
    }
    const columnPairs = props?.initialValue?.columnPairs;
    if (columnPairs){
      const pairs = columnPairs
        .map(p => ({title:(p?.sourceColumn?.name || '') + '-' + ( p?.targetColumn?.name || ''),key:(p?.sourceColumn?.name || '') + ':' + ( p?.targetColumn?.name || '')}));
      setCheckedKeys(pairs.map(i => i.key));
      setCheckedData(pairs);
    }
  }, [props?.initialValue]);



  // 源映射字段拖拽
  const onDrop: TreeProps['onDrop'] = (info) => {
    const dropKey = info.node.key;
    const dragKey = info.dragNode.key;
    const dropPos = info.node.pos.split('-');
    const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]); // the drop position relative to the drop node, inside 0, top -1, bottom 1
    const data = [...checkedData];
    // Find dragObject and  drop index
    let dragObj: TreeDataNode;
    lookup(data, dragKey, (item, index, arr) => {
      arr.splice(index, 1);
      dragObj = item;
    });
    let ar: TreeDataNode[] = [];
    let matchIndex: number;
    lookup(data, dropKey, (_item, index, arr) => {
      ar = arr;
      matchIndex = index;
    });
    if (dropPosition === -1) {
      // Drop on the top of the drop node
      ar.splice(matchIndex!, 0, dragObj!);
    } else {
      // Drop on the bottom of the drop node
      ar.splice(matchIndex! + 1, 0, dragObj!);
    }
    setCheckedData(ar);
  };



  const onChecked: TreeProps['onCheck'] = (checkedKeys) => {
    const k = checkedKeys as React.Key[];
    const checkedTreeData = treeData.filter(n => (k.indexOf(n.key) > -1))
    setCheckedKeys(checkedTreeData.map(i => i.key));
    setCheckedData(checkedTreeData);
  }


  const onAllAdd = () => {
    setCheckedData(treeData);
    setCheckedKeys(treeData.map(i => i.key));
  };

  const onAllRemove = () => {
    setCheckedData([]);
    setCheckedKeys([]);
  };

  // 源选中字段移除
  const onRemoveClick = (node: TreeDataNode) => {
    onRemove(node, checkedData, (nd, n) => {
      setCheckedData(nd);
      const k = [...checkedKeys];
      for (let i = 0; i < k.length; i++) {
        let key = k[i];
        if (key === n.key) {
          k.splice(i, 1);
          setCheckedKeys(k);
          break;
        }
      }
    })
  }

  return (<>
    <Row gutter={[12, 12]} style={{width: 600}} justify={'center'}>
      <Col span={10}>
          <div className={styles.wrapContainer}>
            <Tree
              blockNode={true}
              checkable={true}
              selectable={false}
              autoExpandParent={false}
              defaultExpandParent={false}
              checkedKeys={checkedKeys}
              onCheck={onChecked}
              treeData={treeData}
              height={290}
              className={styles.treeData}
            />
          </div>
      </Col>
      <Col span={3} style={{display:'inline-flex', flexDirection:'column',justifyContent: 'space-evenly'}}>
          <Tooltip title={'添加全部'}>
            <Button type={'default'} onClick={onAllAdd}><DoubleRightOutlined/></Button>
          </Tooltip>
          <Tooltip title={'移除全部'} placement={'top'}>
            <Button type={'default'} onClick={onAllRemove}><DoubleLeftOutlined/></Button>
          </Tooltip>
      </Col>
      <Col span={10}>
        <div className={styles.wrapContainer}>
          <Tree
            height={290}
            treeData={checkedData}
            onDrop={onDrop}
            draggable={true}
            blockNode={true}
            titleRender={(node) => {
              const {title} = node;
              return (
                <div className="treeItem">
                  <div className="name">
                    <Space>
                      <span>{`${title}`}</span>
                      <a
                        onClick={() => onRemoveClick(node)}>
                        <MinusCircleOutlined/>
                      </a>
                    </Space>
                  </div>
                </div>);
            }}
          />
        </div>
      </Col>
    </Row>
  </>);
}

export default ColumnGroup;
